package cn.zorbus.common;

import cn.zorbus.common.view.IView1;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import static cn.zorbus.common.ResultMessage.CLIENT_ERROR_CODE;
import static cn.zorbus.common.ResultMessage.CLIENT_ERROR_MESSAGE;
import static cn.zorbus.common.ResultMessage.EVERYTHING_IS_OK_CODE;
import static cn.zorbus.common.ResultMessage.EVERYTHING_IS_OK_MESSAGE;

/**
 * create in 2023/12/20 17:34
 *
 * @author shishaodong
 * @version 0.0.1
 */

@Getter
@Setter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {

    /**
     * 状态码. 参考 阿里巴巴 开发手册 嵩山版 附3 错误码列表
     */
    @JsonView(IView1.class)
    private String code;

    /**
     * 返回给前端的数据
     */
    @Getter
    @JsonView(IView1.class)
    private T data;

    /**
     * 给前端的提示语
     */
    @JsonView(IView1.class)
    private String message;

    /**
     * 判断是否有数据
     *
     * @return bool
     */
    public boolean hasData() {
        return !Objects.isNull(data);
    }

    /**
     * 广泛上的成功
     *
     * @param <T> data
     * @return result
     */
    public static <T> Result<T> success() {
        return Result.<T>builder()
                .message(EVERYTHING_IS_OK_MESSAGE)
                .code(EVERYTHING_IS_OK_CODE)
                .build();
    }

    /**
     * 自定义 message
     *
     * @param message 自定义 message
     * @param <T>     data
     * @return result
     */
    public static <T> Result<T> success(String message) {
        return Result.<T>builder()
                .message(message)
                .code(EVERYTHING_IS_OK_CODE)
                .build();
    }

    /**
     * 自定义 message
     *
     * @param message 自定义 message
     * @param <T>     data
     * @return result
     */
    public static <T> Result<T> success(String status, String message) {
        return Result.<T>builder()
                .message(message)
                .code(status)
                .build();
    }

    /**
     * 自定义数据
     *
     * @param data 数据
     * @param <T>  data
     * @return result
     */
    public static <T> Result<T> success(T data) {
        return Result.<T>builder()
                .message(EVERYTHING_IS_OK_MESSAGE)
                .code(EVERYTHING_IS_OK_CODE)
                .data(data)
                .build();
    }

    /**
     * 自定义数据
     *
     * @param data 数据
     * @param <T>  data
     * @return result
     */
    public static <T> Result<T> success(String status, String message, T data) {
        return Result.<T>builder()
                .message(message)
                .code(status)
                .data(data)
                .build();
    }

    /**
     * failure
     *
     * @param <T> data
     * @return result
     */
    public static <T> Result<T> failure() {
        return Result.<T>builder()
                .message(CLIENT_ERROR_MESSAGE)
                .code(CLIENT_ERROR_CODE)
                .build();
    }

    /**
     * failure
     *
     * @param message 自定义 message
     * @param <T>     data
     * @return result
     */
    public static <T> Result<T> failure(String message) {
        return Result.<T>builder()
                .message(message)
                .code(CLIENT_ERROR_CODE)
                .build();
    }

    /**
     * failure
     *
     * @param message 自定义 message
     * @param <T>     data
     * @return result
     */
    public static <T> Result<T> failure(String status, String message) {
        return Result.<T>builder()
                .message(message)
                .code(CLIENT_ERROR_CODE)
                .build();
    }


    /**
     * 获取数据或者抛出异常
     *
     * @param exceptionSupplier exceptionSupplier
     * @param <X>               exceptionSupplier
     * @return T
     * @throws X exceptionSupplier
     */
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (data != null) {
            return data;
        } else {
            throw exceptionSupplier.get();
        }
    }

    /**
     * 判断处理是否成功
     *
     * @return boolean
     */
    public boolean isSuccess() {
        return StringUtils.equalsIgnoreCase(EVERYTHING_IS_OK_CODE, code);
    }

    /**
     * 获取或者给出默认值
     *
     * @param t 默认值
     * @return T
     */
    public T getOrDefault(T t) {
        return Objects.isNull(data) ? t : data;
    }


    /**
     * 获取不到给一个默认的对象
     *
     * @param supplier Supplier
     * @return T
     */
    public T getOrDefault(Supplier<T> supplier) {
        return Objects.isNull(data) ? supplier.get() : data;
    }


    /**
     * 如果获取到则进行消费
     *
     * @param consumer consumer
     */
    public void ifAvailable(@NotNull Consumer<T> consumer) {
        consumer.accept(this.data);
    }

    /**
     * 该函数的功能是：如果code与EVERYTHING_IS_OK_CODE相等（不区分大小写），
     * 则调用consumer的accept方法，将data作为参数传递给consumer。
     *
     * @param consumer consumer
     */
    public void ifSuccess(@NotNull Consumer<T> consumer) {
        if (StringUtils.equalsIgnoreCase(EVERYTHING_IS_OK_CODE, code)) {
            consumer.accept(data);
        }
    }

    public void ifFailure(@NotNull Consumer<T> consumer) {
        if (!StringUtils.equalsIgnoreCase(EVERYTHING_IS_OK_CODE, code)) {
            consumer.accept(data);
        }
    }

    public <U> U map(@NotNull Function<? super T, ? extends U> converter) {
        return converter.apply(data);
    }
}
